
#include <iostream>
#include <assert.h>

using namespace std;

class Date
{
    friend ostream& operator<<(ostream& out, const Date& d);
    friend istream& operator>>(istream& in, Date& d);

public:

    Date(int year = 1, int month = 1, int day = 1)
        :_year(year)
         ,_month(month)
         ,_day(day)
    {
        assert(Check());
    }

    // 拷贝构造
    // 复制重载
    // 析构函数
    // 可以不用写
    // 对于Date类默认生成的就够用

    void print() const 
    {
        cout << _year << '/' << _month << '/' << _day << endl;
    }

    int GetMonthDay(int year, int month) const 
    {
        static int Aday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
        {
            return 29;
        }

        return Aday[month];
    }

    bool Check() const 
    {
        if (_year >= 1 && _month >= 1 && _month <= 12 && _day >= 1 && _day <= GetMonthDay(_year, _month))
        {
            return true;
        }

        return false;
    }

    bool operator==(const Date& d) const 
    {
        return _year == d._year && _month == d._month && _day == d._day;
    }

    bool operator!=(const Date& d) const 
    {
        return !(*this == d);
    }

    bool operator<(const Date& d) const 
    {
        if (_year < d._year)
        {
            return true;
        }
        else if (_year == d._year && _month < d._month)
        {
            return true;
        }
        else if (_year == d._year && _month == d._month && _day < d._day)
        {
            return true;
        }

        return false;
    }

    bool operator<=(const Date& d) const 
    {
        return *this < d || *this == d;
    }

    bool operator>(const Date& d) const 
    {
        return !(*this <= d);
    }

    bool operator>=(const Date& d) const 
    {
        return !(*this < d);
    }

    Date& operator++()
    {
        *this += 1;
        return *this;
    }

    Date operator++(int)
    {
        Date tmp(*this);
        *this += 1;

        return tmp;
    }

    Date& operator--()
    {
        *this -= 1;
        return *this;
    }

    Date operator--(int)
    {
        Date tmp(*this);
        *this -= 1;

        return tmp;
    }

    Date& operator+=(int day)
    {
        if (day < 0)
        {
            return *this -= -day;
        }

        _day += day;

        while (_day > GetMonthDay(_year, _month))
        {
            _day -= GetMonthDay(_year, _month);
            ++ _month;

            if (_month == 13)
            {
                _month = 1;
                _year ++ ;
            }
        }

        return *this;
    }

    Date operator+(int day)
    {
        Date tmp(*this);
        tmp += day;

        return tmp;
    }

    Date& operator-=(int day)
    {
        if (day < 0)
        {
            return *this += -day;
        }

        _day -= day;
        while (_day <= 0)
        {
            -- _month;
            if (_month == 0)
            {
                _month = 12;
                _year -- ;
            }

            _day += GetMonthDay(_year, _month);
        }

        return *this;
    }

    Date operator-(int day)
    {
        Date tmp(*this);
        tmp -= day;

        return tmp;
    }
    
    int operator-(const Date& d) const 
    {
        int flag = 1;
        Date max = *this;
        Date min = d;

        if (*this < d)
        {
            max = d;
            min = *this;
            flag = -1;
        }

        int count = 0;

        while (min != max)
        {
            ++ min;
            ++ count; 
        }

        return count * flag;
    }

private:
    
    int _year;
    int _month;
    int _day;

};

ostream& operator<<(ostream& out, const Date& d)
{
    cout << d._year << "年" << d._month << "月" << d._day << "日";
    return out;
}

istream& operator>>(istream& in, Date& d)
{
    in >> d._year >> d._month >> d._day;
    assert(d.Check());

    return in;
}
